home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / winsock / ircii2-6.zip / SRC\IRCII-2.6\SOURCE\IRCFLUSH.C < prev    next >
C/C++ Source or Header  |  1994-12-28  |  3KB  |  154 lines

  1. /*
  2.  * Flush: A little program that tricks another program into line buffering
  3.  * its output. 
  4.  *
  5.  * By Michael Sandrof 
  6.  */
  7.  
  8. #ifndef lint
  9. static    char    rcsid[] = "@(#)$Id: ircflush.c,v 1.16 1994/07/02 02:32:13 mrg Stab $";
  10. #endif
  11.  
  12. #include "irc.h"
  13. #include <sys/wait.h>
  14.  
  15. #ifndef __linux__
  16. # ifdef __svr4__
  17. #  include <sys/termios.h>
  18. # else
  19. #  include <sgtty.h>    /* SVR4 => sgtty = yuk */
  20. # endif /* SOLARIS */
  21. #endif /* __linux__ */
  22.  
  23.  
  24. #define BUFFER_SIZE 1024
  25.  
  26. /* descriptors of the tty and pty */
  27.     int    master,
  28.         slave;
  29.     pid_t    pid;
  30.  
  31. RETSIGTYPE death();
  32.  
  33. RETSIGTYPE death()
  34. {
  35.     close(0);
  36.     close(master);
  37.     kill(pid, SIGKILL);
  38.     wait(0);
  39.     exit(0);
  40. }
  41.  
  42. /*
  43.  * setup_master_slave: this searches for an open tty/pty pair, opening the
  44.  * pty as the master device and the tty as the slace device 
  45.  */
  46. void    setup_master_slave()
  47. {
  48.     char    line[11];
  49.     char    linec;
  50.     int    linen;
  51.  
  52.     for (linec = 'p'; linec <= 's'; linec++)
  53.     {
  54.         sprintf(line, "/dev/pty%c0", linec);
  55.         if (access(line, 0) != 0)
  56.             break;
  57.         for (linen = 0; linen < 16; linen++)
  58.         {
  59.             sprintf(line, "/dev/pty%c%1x", linec, linen);
  60.             if ((master = open(line, O_RDWR)) >= 0)
  61.             {
  62.                 sprintf(line, "/dev/tty%c%1x", linec, linen);
  63.                 if (access(line, R_OK | W_OK) == 0)
  64.                 {
  65.                     if ((slave = open(line, O_RDWR)) >= 0)
  66.                         return;
  67.                 }
  68.                 close(master);
  69.             }
  70.         }
  71.     }
  72.     fprintf(stderr, "flush: Can't find a pty\n");
  73.     exit(0);
  74. }
  75.  
  76. /*
  77.  * What's the deal here?  Well, it's like this.  First we find an open
  78.  * tty/pty pair.  Then we fork three processes.  The first reads from stdin
  79.  * and sends the info to the master device.  The next process reads from the
  80.  * master device and sends stuff to stdout.  The last processes is the rest
  81.  * of the command line arguments exec'd.  By doing all this, the exec'd
  82.  * process is fooled into flushing each line of output as it occurs.  
  83.  */
  84. void    main(argc, argv)
  85. int    argc;
  86. char    **argv;
  87. {
  88.     char    buffer[BUFFER_SIZE];
  89.     int    cnt;
  90.     fd_set    rd;
  91.  
  92.     if (argc < 2)
  93.     {
  94.         fprintf(stderr, "Usage: %s [program] [arguments to program]\n", argv[0]);
  95.         exit(1);
  96.     }
  97.     pid = open("/dev/tty", O_RDWR);
  98. #ifdef HAVE_SETSID
  99.     setsid();
  100. #else
  101.     ioctl(pid, TIOCNOTTY, 0);
  102. #endif /* HAVE_SETSID */
  103.     setup_master_slave();
  104.     switch (pid = fork())
  105.     {
  106.     case -1:
  107.         fprintf(stderr, "flush: Unable to fork process!\n");
  108.         exit(1);
  109.     case 0:
  110.         dup2(slave, 0);
  111.         dup2(slave, 1);
  112.         dup2(slave, 2);
  113.         close(master);
  114.         setuid(getuid());
  115.         setgid(getgid());
  116.         execvp(argv[1], &(argv[1]));
  117.         fprintf(stderr, "flush: Error exec'ing process!\n");
  118.         exit(1);
  119.         break;
  120.     default:
  121.         (void) MY_SIGNAL(SIGCHLD, death, 0);
  122.         close(slave);
  123.         while (1)
  124.         {
  125.             FD_ZERO(&rd);
  126.             FD_SET(master, &rd);
  127.             FD_SET(0, &rd);
  128.             switch (select(NFDBITS, &rd, 0, 0, 0))
  129.             {
  130.             case -1:
  131.             case 0:
  132.                 break;
  133.             default:
  134.                 if (FD_ISSET(0, &rd))
  135.                 {
  136.                     if ((cnt = read(0, buffer,BUFFER_SIZE)) > 0)
  137.                     write(master, buffer, cnt);
  138.                     else
  139.                     death();
  140.                 }
  141.                 if (FD_ISSET(master, &rd))
  142.                 {
  143.                     if ((cnt = read(master, buffer,
  144.                             BUFFER_SIZE)) > 0)
  145.                         write(1, buffer, cnt);
  146.                     else
  147.                         death();
  148.                 }
  149.             }
  150.         }
  151.         break;
  152.     }
  153. }
  154.